package com.pine.dcts.taskScheduling.scheduler;


import com.alibaba.fastjson.JSON;
import com.pine.dcts.taskScheduling.common.Constants;
import com.pine.dcts.taskScheduling.job.AbstractJob;
import org.quartz.*;
import org.quartz.Trigger.TriggerState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;

public class DynamicScheduler {

    private static final Logger log = LoggerFactory.getLogger(DynamicScheduler.class);

    // scheduler
    private static Scheduler scheduler;


    //调度名称
    public static final String SCHEDULER_NAME = "scheduler";

    private static String key = "key";

    /**
     * 构建触发器
     *
     * @param taskCfg
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Trigger buildTrigger(AbstractJob taskCfg) {
        TriggerKey triggerKey = TriggerKey.triggerKey(taskCfg.getId(), taskCfg.getGroupId());
        TriggerBuilder builder = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey).startNow();
        //如果是core表达式
        if (Constants.CORE_TASK.equals(taskCfg.getCoreType())) {
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder
                    .cronSchedule(taskCfg.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();// 时间调度
            return builder.withSchedule(cronScheduleBuilder)
                    .build();
        }
        // 设置执行策略

        // 时间间隔
        if (Constants.GAP_TASK.equals(taskCfg.getExeType())) {
            if (0 != taskCfg.getMinnum()) {
                // 间隔分钟
                Integer minnum = taskCfg.getMinnum();
                if (taskCfg.getHournum() != null && 0 != taskCfg.getHournum()) {
                    minnum += taskCfg.getHournum() * 60;
                }
                builder.withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInMinutes(minnum).repeatForever());
            } else {
                // 间隔小时执行
                builder.withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInHours(taskCfg.getHournum())
                        .repeatForever());
            }
        }
        // 单次执行
        if (Constants.SINGLE_TASK.equals(taskCfg.getExeType())) {
            builder.withSchedule(CronScheduleBuilder.cronSchedule(getCron(new Date(taskCfg.getExecutetime()))));
        }
        // 每月
        if (Constants.MONTH_TASK.equals(taskCfg.getExeType())) {
            builder.withSchedule(CronScheduleBuilder
                    .monthlyOnDayAndHourAndMinute(taskCfg.getDay(),
                            taskCfg.getHour(), taskCfg.getMinute()));
        }
        // 每周
        if (Constants.WEEKLY_TASK.equals(taskCfg.getExeType())) {
            builder.withSchedule(CronScheduleBuilder
                    .weeklyOnDayAndHourAndMinute(Integer.valueOf(taskCfg.getWeek()) + 1,
                            taskCfg.getHour(), taskCfg.getMinute()));

        }
        // 每天
        if (Constants.DAILY_TASK.equals(taskCfg.getExeType())) {
            builder.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(
                    taskCfg.getHour(), taskCfg.getMinute()));
        }
        return builder.build();
    }

    public static String getCron(Date date) {
        String dateFormat = "ss mm HH dd MM ? yyyy";

        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        String formatTimeStr = null;
        if (date != null) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }


    public static void setScheduler(Scheduler scheduler) {
        DynamicScheduler.scheduler = scheduler;
    }

    /**
     * 添加任务
     *
     * @param job
     * @return
     * @throws SchedulerException boolean
     * @methodName addJob
     * @author dcits.xiaoyuan
     * @date 2017年8月28日
     */
    public static boolean addJob(AbstractJob job) throws SchedulerException {
        // TriggerKey valid if_exists
        if (checkExists(job.getId(), job.getGroupId())) {
            log.info("任务已存在, jobGroup:{}, jobName:{}", job.getId(), job.getGroupId());
            return false;
        }
        Trigger cronTrigger = buildTrigger(job);
        JobDetail jobDetail = JobBuilder.newJob(job.getClass())
                .withIdentity(job.getId(), job.getGroupId())
                .storeDurably(job.isDurability())
                .requestRecovery(job.isShouldRecover()).build();
        jobDetail.getJobDataMap().put(SCHEDULER_NAME, JSON.toJSONString(job));
        // schedule : jobDetail + cronTrigger
        Date date = scheduler.scheduleJob(jobDetail, cronTrigger);
        log.info("添加任务成功：, jobDetail:{}, cronTrigger:{}, date:{}", jobDetail, cronTrigger, date);
        return true;
    }

    /**
     * 修改任务
     *
     * @param job
     * @return
     * @throws SchedulerException boolean
     * @methodName rescheduleJob
     * @author dcits.xiaoyuan
     * @date 2017年8月28日
     */
    public static boolean rescheduleJob(AbstractJob job) throws SchedulerException {
        // TriggerKey valid if_exists
        if (!checkExists(job.getId(), job.getGroupId())) {
            log.info("修改任务失败，任务不存在, JobGroup:{}, JobName:{}", job.getId(), job.getGroupId());
            return false;
        }
        // TriggerKey : name + group
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), job.getGroupId());
        CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        if (oldTrigger != null) {
            // avoid repeat
//            String oldCron = oldTrigger.getCronExpression();
//            if (oldCron.equals(job.getCronExpression())){
//                return true;
//            }
//            // CronTrigger : TriggerKey + cronExpression
//            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
//            oldTrigger = oldTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
            // rescheduleJob
            scheduler.rescheduleJob(triggerKey, buildTrigger(job));
        } else {
            // CronTrigger : TriggerKey + cronExpression
//            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
//            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();

            // JobDetail-JobDataMap fresh
            JobKey jobKey = new JobKey(job.getId(), job.getGroupId());
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            jobDetail.getJobDataMap().put(SCHEDULER_NAME, JSON.toJSONString(job));
            // Trigger fresh
            HashSet<Trigger> triggerSet = new HashSet<Trigger>();
            triggerSet.add(buildTrigger(job));

            scheduler.scheduleJob(jobDetail, triggerSet, true);
        }

        log.info("修改任务成功, JobGroup:{}, JobName:{}", job.getId(), job.getGroupId());
        return true;
    }

    /**
     * 检查任务是否存在
     *
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException boolean
     * @methodName checkExists
     * @author dcits.xiaoyuan
     * @date 2017年8月28日
     */

    public static boolean checkExists(String jobName, String jobGroup) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        return scheduler.checkExists(triggerKey);
    }


    /**
     * 删除任务
     *
     * @return
     * @throws SchedulerException
     */
    public static boolean removeJob(AbstractJob job) throws SchedulerException {
        // TriggerKey : name + group
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), job.getGroupId());
        boolean result = false;
        if (checkExists(job.getId(), job.getGroupId())) {
            result = scheduler.unscheduleJob(triggerKey);
            log.info("删除任务成功, triggerKey:{}, result [{}]", triggerKey, result);
        }
        return true;
    }

    /**
     * 暂停
     *
     * @return
     * @throws SchedulerException
     */
    public static boolean pauseJob(AbstractJob job) throws SchedulerException {
        // TriggerKey : name + group
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), job.getGroupId());

        boolean result = false;
        if (checkExists(job.getId(), job.getGroupId())) {
            scheduler.pauseTrigger(triggerKey);
            result = true;
            log.info("暂停任务成功, triggerKey:{}", triggerKey);
        } else {
            log.info("暂停任务失败, triggerKey:{}", triggerKey);
        }
        return result;
    }

    /**
     * 恢复
     *
     * @return
     * @throws SchedulerException
     */
    public static boolean resumeJob(AbstractJob job) throws SchedulerException {
        // TriggerKey : name + group
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), job.getGroupId());

        boolean result = false;
        if (checkExists(job.getId(), job.getGroupId())) {
            scheduler.resumeTrigger(triggerKey);
            result = true;
            log.info("恢复任务成功, triggerKey:{}", triggerKey);
        } else {
            log.info("恢复任务失败, triggerKey:{}", triggerKey);
        }
        return result;
    }


    /**
     * 立即运行
     *
     * @return
     * @throws SchedulerException
     */
    public static boolean triggerJob(AbstractJob job) throws SchedulerException {
        // TriggerKey : name + group
        JobKey jobKey = new JobKey(job.getId(), job.getGroupId());

        boolean result = false;
        if (checkExists(job.getId(), job.getGroupId())) {
            scheduler.triggerJob(jobKey);
            result = true;
            log.info("立即运行任务成功, jobKey:{}", jobKey);
        } else {
            DynamicScheduler.addJob(job);
            scheduler.triggerJob(jobKey);
            log.info("立即运行任务失败, jobKey:{}", jobKey);
        }
        return result;
    }

    public static int jobStatus(AbstractJob job) {
        int result = -1;
        // TriggerKey : name + group
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), job.getGroupId());
        TriggerState result1 = null;
        try {
            result1 = scheduler.getTriggerState(triggerKey);
            if (result1 != null) {
                if ("NONE".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_NONE;
                } else if ("NORMAL".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_NORMAL;
                } else if ("PAUSED".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_PAUSED;
                } else if ("COMPLETE".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_COMPLETE;
                } else if ("ERROR".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_ERROR;
                } else if ("BLOCKED".equals(result1.name())) {
                    result = Constants.JobStatus.STATE_BLOCKED;
                }
            }
        } catch (SchedulerException e) {
            log.info("获取任务状态错误, jobName:{}", job.getJobName());
        }

        return result;

    }


//
//	/**
//	 * 获取所有任务
//	 * @methodName getAllJobs
//	 * @author dcits.xiaoyuan
//	 * @date 2017年8月28日
//	 * @return
//	 * @throws SchedulerException
//	 * List<ScheduleJob>
//	 */
//	public static List<? extends AbstractJob> getAllJobs()throws SchedulerException{
//		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
//		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
//		List<? extends AbstractJob> jobList = new ArrayList<>();
//		for (JobKey jobKey : jobKeys) {
//		    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
//		    for (Trigger trigger : triggers) {
//				AbstractJob job = new AbstractJob();
//		        job.setId(jobKey.getName());
//		     //   job.set(jobKey.getGroup());
//		        job.setRemarks("触发器:" + trigger.getKey());
//		        TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
//		       // job.setJobStatus(triggerState.name());
//		        if (trigger instanceof support.CronTrigger) {
//		            support.CronTrigger cronTrigger = (support.CronTrigger) trigger;
//		            String cronExpression = cronTrigger.getCronExpression();
//		            job.setCronExpression(cronExpression);
//		        }
//		        jobList.add(job);
//		    }
//		}
//
//		return jobList;
//	}
//
//
//	/**
//	 * 获取所有运行的任务
//	 * @methodName getAllExecutingJobs
//	 * @author dcits.xiaoyuan
//	 * @date 2017年8月28日
//	 * @return
//	 * @throws SchedulerException
//	 * List<ScheduleJob>
//	 */
//	public static List<ScheduleJob> getAllExecutingJobs() throws SchedulerException{
//		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
//		List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
//		for (JobExecutionContext executingJob : executingJobs) {
//		    ScheduleJob job = new ScheduleJob();
//		    JobDetail jobDetail = executingJob.getJobDetail();
//		    JobKey jobKey = jobDetail.getKey();
//		    Trigger trigger = executingJob.getTrigger();
//		    job.setId(jobKey.getName());
//		   // job.setJobGroup(jobKey.getGroup());
//		    job.setRemarks("触发器:" + trigger.getKey());
//		    TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
//		    //job.setJobStatus(triggerState.name());
//		    if (trigger instanceof support.CronTrigger) {
//		        support.CronTrigger cronTrigger = (CronTrigger) trigger;
//		        String cronExpression = cronTrigger.getCronExpression();
//		        job.setCronExpression(cronExpression);
//		    }
//		    jobList.add(job);
//		}
//
//		return jobList;
//	}

}
